﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;

using Pibby.Core.IO;
//using Pibby.Core.PortableMedia;

namespace Pibby
{
	public class RemovableDriveDetector : Pibby.Core.IO.RemovableDriveDetector
	{
		#region Methods

		#region Win32 constants
		
		/// <summary>
		/// Windows message we are looking for...
		/// </summary>
		private const int WM_DEVICECHANGE = 0x0219;
		
		/// <summary>
		/// A device or piece of media has been inserted and is now available
		/// </summary>
		private const int DBT_DEVICEARRIVAL			= 0x8000; 

		/// <summary>
		/// A device or piece of media has been removed.
		/// </summary>
		private const int DBT_DEVICEREMOVECOMPLETE	= 0x8004; // removed 

		private const int DBT_DEVTYP_DEVICEINTERFACE = 5;
		private const int DBT_DEVTYP_HANDLE = 6;
		private const int BROADCAST_QUERY_DENY = 0x424D5144;
		private const int DBT_DEVTYP_VOLUME = 0x00000002; // drive type is logical volume

		[StructLayout(LayoutKind.Sequential)]
		public struct DEV_BROADCAST_VOLUME
		{
			public int dbcv_size;
			public int dbcv_devicetype;
			public int dbcv_reserved;
			public int dbcv_unitmask;
		}
	
		#endregion

		public void CheckDeviceChange(ref Message windowsMessage)
		{
			if (windowsMessage.Msg == WM_DEVICECHANGE)
			{
				switch (windowsMessage.WParam.ToInt32())
				{
					case DBT_DEVICEARRIVAL:
						
						{
							int devType = Marshal.ReadInt32(windowsMessage.LParam, 4);

							if (devType == DBT_DEVTYP_VOLUME)
							{
								DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(windowsMessage.LParam, typeof(DEV_BROADCAST_VOLUME));

                                this.SignalDeviceArrival(vol.dbcv_unitmask);
							}
						}
						
						break;

					case DBT_DEVICEREMOVECOMPLETE:
						{
							int devType = Marshal.ReadInt32(windowsMessage.LParam, 4);

							if (devType == DBT_DEVTYP_VOLUME)
							{
								devType = Marshal.ReadInt32(windowsMessage.LParam, 4);
								
								if (devType == DBT_DEVTYP_VOLUME)
								{
									DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME) Marshal.PtrToStructure(windowsMessage.LParam, typeof(DEV_BROADCAST_VOLUME));
									
                                    this.SignalDeviceRemoval(vol.dbcv_unitmask);
								}
							}
						}

						break;
				}
			}
		}

		#endregion
	}
}
